using System.Collections.Generic;
using System.Collections;
using System.ComponentModel;
using System.Linq;
using System.Linq.Expressions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MongoDB.Bson;
using MongoDB.Driver;
using MongoDB.Driver.Builders;
using MongoDB.Dynamic;
using MongoDynamic.Tests.Driver;

namespace MongoDynamic.Tests
{
    [TestClass]
    public class EagerLoadingTests
    {
        [TestInitialize]
        public void Initialize()
        {
            Dynamic.Configure(notifyProperyChanged: true);

            Dynamic.Config.SetKeyName<ICustomer>(c => c.Id);
            Dynamic.Config.SetKeyName<IOrder>(o => o.Id);
            Dynamic.Config.LoadCollection<ICustomer, IOrder>(customer => customer.Orders, order => order.IdCustomer);
            Dynamic.Config.LoadFK<IOrder, ICustomer>(order => order.Customer, order => order.IdCustomer);
            var customers = Dynamic.GetCollection<ICustomer>();
            var orders = Dynamic.GetCollection<IOrder>();
            customers.RemoveAll(true);
            orders.RemoveAll(true);
        }

        [TestMethod]
        public void TesteRemoveAllCountEqualsZero()
        {
            var customers = Dynamic.GetCollection<ICustomer>();
            var orders = Dynamic.GetCollection<IOrder>();
            Assert.IsTrue(customers.Count() == 0);
            Assert.IsTrue(orders.Count() == 0);
        }

        [TestMethod]
        public void TesteInsertCustomerAndOrder()
        {
            DynamicCollection<ICustomer> customers = Dynamic.GetCollection<ICustomer>();
            DynamicCollection<IOrder> orders = Dynamic.GetCollection<IOrder>();

            ICustomer customer = customers.New();
            customer.Name = "Jone";
            customers.Upsert(customer);

            var orderA = orders.New();
            orderA.IdCustomer = customer.Id;
            orders.Upsert(orderA);

            Assert.IsTrue(customers.All().Any(c => c.Id == customer.Id));
        }

        [TestMethod]
        public void TesteLoadCustomerByOrders()
        {
            var customers = Dynamic.GetCollection<ICustomer>();
            var orders = Dynamic.GetCollection<IOrder>();
            var dummy = orders.New();
            var cust = customers.New();
            cust.Name = "teste";
            customers.Upsert(cust);
            dummy.IdCustomer = cust.Id;
            orders.Upsert(dummy);

            var order = orders.GetFirstOrDefault(o => o.IdCustomer > 0);
            Assert.IsNotNull(order);

            Assert.IsNotNull(order.Customer);
        }

        [TestMethod]
        public void TestLoadOrderByCustomerManually()
        {
            var customers = Dynamic.GetCollection<ICustomer>();
            var orders = Dynamic.GetCollection<IOrder>();

            var customer = customers.New();
            customer.Name = "Jone";
            customers.Upsert(customer);
            Assert.IsTrue(customer.Id > 0);

            var orderline = orders.New();
            orderline.IdCustomer = customer.Id;
            orders.Upsert(orderline);

            var id = customer.Id;
            var orderLines = orders.CustomQuery(o => o.IdCustomer == id);
            Assert.IsTrue(orderLines.Count() == 1);
        }

        [TestMethod]
        public void TestLoadOrderByCustomerAuto()
        {
            var customers = Dynamic.GetCollection<ICustomer>();
            var orders = Dynamic.GetCollection<IOrder>();

            var cust = customers.New();
            cust.Name = "X";
            customers.Upsert(cust);

            var check = customers.GetFirstOrDefault();

            var o1 = orders.New();
            o1.IdCustomer = check.Id;
            orders.Upsert(o1);

            var o2 = orders.New();
            o2.IdCustomer = check.Id;
            orders.Upsert(o2);

            var verify = customers.GetFirstOrDefault();

            Assert.IsNotNull(verify.Orders);
            Assert.IsTrue(verify.Orders.Count() == 2);
        }

        [TestMethod]
        public void DataTransferObjectTeste()
        {
            var customers = Dynamic.GetCollection<ICustomer>();

            var customer = new Customer(); // implements ICustomer
            customer.Name = "John";
            customer.ExtraIgnoredField = "some ignored value";

            customers.Upsert(customer);

            Assert.IsTrue(customer.Id > 0);
        }

        [TestMethod]
        public void NotifyPropChanged()
        {
            var customers = Dynamic.GetCollection<ICustomer>(); //get the collection

            var cust = customers.New(); //create a new customer

            var notify = cust as INotifyPropertyChanged; //verify if implements INotifyPropertyChanged

            Assert.IsNotNull(notify); //check if not null

            notify.PropertyChanged += (s, e) =>
                                          {
                                              Assert.IsNotNull(e.PropertyName);
                                          }; //anonymous delegate

            cust.Name = "John";
        }
    }
}